package common;

/**
 * A class representing a Person, with information about the
 * name, the age, the weight and the gender. Person is immutable
 * and is constructed by static factory methods.
 * 
 * @author Fredrik Bystam
 * @version 2011.10.17
 *
 */
public class Person {
	//en kommentar
	/**
	 * A simple enum representing the gender of a {@link Person}
	 */
	public enum Gender { MALE, FEMALE, FALUN };
	// A cache for avoid duplicate Person objects
	static SimpleCache<Person> cache = new SimpleCache<Person>(10);
	
	private final String name;
	private final int age;
	private final float weight;
	private final Gender gender;
	
	/**
	 * Create a new Person using the input specifications. This static factory
	 * uses a cache to avoid duplicate objects.
	 * @param name The name of the person
	 * @param age The age of the person
	 * @param weight The weight of the person
	 * @param gender The gender of the person, specified by {@link Gender}
	 * @return A person object specified by the arguments
	 */
	public static Person newPerson(String name, int age, float weight, Gender gender){
		Person newPerson = new Person(name, age, weight, gender);
		Person returnPerson = cache.match(newPerson);
		return returnPerson;
	}
	
	/**
	 * Create a Person object using the specifications another Person.
	 * NOTE: Using this factory method could eliminate the existence
	 * of duplicate Person objects, which is practical since a 
	 * Person is immutable.
	 * @param p The person you wish to create a new one of
	 * @return A cached version of the input person, or the input argument if the cached
	 * 		   did not contain it
	 */
	public static Person newPerson(Person p){
		return cache.match(p);
	}
	
	// Create a new Person
	private Person (String name, int age, float weight, Gender gender){
		this.name = name;
		this.age = age;
		this.weight = weight;
		this.gender = gender;
	}

	public String getName() { return name; }
	public int getAge() { return age; }
	public float getWeight() { return weight; }
	public Gender getGender() { return gender; }

	@Override public boolean equals(Object o){
		if (!(o instanceof Person))
			return false;
		Person p = (Person)o;
		return p.name.equals(name) && p.age == age 
			   && p.weight == weight && p.gender == gender;
	}
	
	@Override public int hashCode(){
		int result = 31;
		result = result*name.hashCode() + 17;
		result = result*age + 17;
		result = result*Float.floatToIntBits(weight) + 17;
		result = result*gender.hashCode() + 17;
		return result;
	}
}
